// src/utils/request.ts

import axios, {
    AxiosInstance,
    AxiosRequestConfig,
    AxiosResponse,
    AxiosError,
    InternalAxiosRequestConfig
} from 'axios';
import { showMessage } from './message';
import { useLoadingStore } from '@/stores/loading';

// 定义基础响应数据类型
export interface BaseResponse<T = any> {
    code: number;
    message: string;
    data: T;
}

// 定义业务错误类型
export interface BusinessError {
    code: number;
    message: string;
}

// 创建axios实例
const service: AxiosInstance = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL as string,
    timeout: 15000,
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
});

// 请求拦截器
service.interceptors.request.use(
    (config: InternalAxiosRequestConfig) => {
        // 显示全局加载状态
        useLoadingStore().startLoading();

        // 添加token
        const token = localStorage.getItem('token');
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }

        // 添加时间戳防止GET请求缓存
        if (config.method?.toLowerCase() === 'get') {
            config.params = {
                ...config.params,
                _t: new Date().getTime()
            };
        }

        console.log('请求拦截:', config);
        return config;
    },
    (error: AxiosError) => {
        // 关闭加载状态
        useLoadingStore().endLoading();
        return Promise.reject(error);
    }
);

// 响应拦截器
service.interceptors.response.use(
    (response: AxiosResponse): any => {
    // 关闭加载状态
    useLoadingStore().endLoading();

    const { status, data } = response;

    // HTTP状态码在2xx范围内
    if (status >= 200 && status < 300) {
        // 业务状态码处理
        if (data.code === 200) {
            return data;
        } else {
            // 业务错误处理
            handleBusinessError(data.code, data.message);
            return Promise.reject(data);
        }
    } else {
        // HTTP错误处理
        handleHttpError(status);
        return Promise.reject(response);
    }
},
    (error: AxiosError) => {
        // 关闭加载状态
        useLoadingStore().endLoading();

        // 错误处理
        if (error.response) {
            // 服务器返回错误响应
            handleHttpError(error.response.status);
        } else if (error.request) {
            // 请求已发出但没有收到响应
            showMessage('网络错误，请检查您的网络连接', 'error');
        } else {
            // 请求配置错误
            showMessage(`请求配置错误: ${error.message}`, 'error');
        }

        return Promise.reject(error);
    }
);

/**
 * 处理业务错误
 * @param code 业务错误码
 * @param message 错误消息
 */
function handleBusinessError(code: number, message: string): void {
    switch (code) {
        case 401:
            // token过期，跳转到登录页
            showMessage('登录状态已过期，请重新登录', 'error');
            setTimeout(() => {
                window.location.href = '/login';
            }, 1500);
            break;
        case 403:
            showMessage('您没有权限执行此操作', 'error');
            break;
        case 500:
            showMessage(`服务器内部错误: ${message}`, 'error');
            break;
        default:
            showMessage(`业务错误 [${code}]: ${message}`, 'error');
    }
}

/**
 * 处理HTTP错误
 * @param status HTTP状态码
 */
function handleHttpError(status: number): void {
    const errorMessages: Record<number, string> = {
        400: '请求参数错误',
        401: '未授权，请登录',
        403: '拒绝访问',
        404: '请求的资源不存在',
        405: '请求方法不被允许',
        408: '请求超时',
        500: '服务器内部错误',
        501: '服务未实现',
        502: '网关错误',
        503: '服务不可用',
        504: '网关超时',
        505: 'HTTP版本不受支持'
    };

    const message = errorMessages[status] || `连接错误 ${status}`;
    showMessage(message, 'error');
}

/**
 * 封装通用请求方法
 * @param config 请求配置
 */
export function request<T = any>(config: AxiosRequestConfig): Promise<BaseResponse<T>> {
    return service(config);
}

/**
 * 封装GET请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 额外配置
 */
export function get<T = any>(
    url: string,
    params?: object,
    config?: AxiosRequestConfig
): Promise<BaseResponse<T>> {
    return service.get(url, { ...config, params });
}

/**
 * 封装POST请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 额外配置
 */
export function post<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig
): Promise<BaseResponse<T>> {
    return service.post(url, data, config);
}

/**
 * 封装PUT请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 额外配置
 */
export function put<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig
): Promise<BaseResponse<T>> {
    return service.put(url, data, config);
}

/**
 * 封装DELETE请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 额外配置
 */
export function del<T = any>(
    url: string,
    params?: object,
    config?: AxiosRequestConfig
): Promise<BaseResponse<T>> {
    return service.delete(url, { ...config, params });
}

export default service;